home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-SPAR.{_6 / UACCESS.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  14KB  |  400 lines

  1. /* $Id: uaccess.h,v 1.17 1998/09/16 12:25:29 jj Exp $
  2.  * uaccess.h: User space memore access functions.
  3.  *
  4.  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  5.  * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  6.  */
  7. #ifndef _ASM_UACCESS_H
  8. #define _ASM_UACCESS_H
  9.  
  10. #ifdef __KERNEL__
  11. #include <linux/sched.h>
  12. #include <linux/string.h>
  13. #include <asm/vac-ops.h>
  14. #include <asm/a.out.h>
  15. #endif
  16.  
  17. #ifndef __ASSEMBLY__
  18.  
  19. /* Sparc is not segmented, however we need to be able to fool verify_area()
  20.  * when doing system calls from kernel mode legitimately.
  21.  *
  22.  * "For historical reasons, these macros are grossly misnamed." -Linus
  23.  */
  24.  
  25. #define KERNEL_DS   ((mm_segment_t) { 0 })
  26. #define USER_DS     ((mm_segment_t) { -1 })
  27.  
  28. #define VERIFY_READ    0
  29. #define VERIFY_WRITE    1
  30.  
  31. #define get_ds()    (KERNEL_DS)
  32. #define get_fs()    (current->tss.current_ds)
  33. #define set_fs(val)    ((current->tss.current_ds) = (val))
  34.  
  35. #define segment_eq(a,b)    ((a).seg == (b).seg)
  36.  
  37. /* We have there a nice not-mapped page at page_offset - PAGE_SIZE, so that this test
  38.  * can be fairly lightweight.
  39.  * No one can read/write anything from userland in the kernel space by setting
  40.  * large size and address near to page_offset - a fault will break his intentions.
  41.  */
  42. #define __user_ok(addr,size) ((addr) < STACK_TOP)
  43. #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
  44. #define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size)))
  45. #define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
  46.  
  47. extern inline int verify_area(int type, const void * addr, unsigned long size)
  48. {
  49.     return access_ok(type,addr,size)?0:-EFAULT;
  50. }
  51.  
  52. /*
  53.  * The exception table consists of pairs of addresses: the first is the
  54.  * address of an instruction that is allowed to fault, and the second is
  55.  * the address at which the program should continue.  No registers are
  56.  * modified, so it is entirely up to the continuation code to figure out
  57.  * what to do.
  58.  *
  59.  * All the routines below use bits of fixup code that are out of line
  60.  * with the main instruction path.  This means when everything is well,
  61.  * we don't even have to jump over them.  Further, they do not intrude
  62.  * on our cache or tlb entries.
  63.  *
  64.  * There is a special way how to put a range of potentially faulting
  65.  * insns (like twenty ldd/std's with now intervening other instructions)
  66.  * You specify address of first in insn and 0 in fixup and in the next
  67.  * exception_table_entry you specify last potentially faulting insn + 1
  68.  * and in fixup the routine which should handle the fault.
  69.  * That fixup code will get
  70.  * (faulting_insn_address - first_insn_in_the_range_address)/4
  71.  * in %g2 (ie. index of the faulting instruction in the range).
  72.  */
  73.  
  74. struct exception_table_entry
  75. {
  76.         unsigned long insn, fixup;
  77. };
  78.  
  79. /* Returns 0 if exception not found and fixup otherwise.  */
  80. extern unsigned long search_exception_table(unsigned long, unsigned long *);
  81.  
  82. extern void __ret_efault(void);
  83.  
  84. /* Uh, these should become the main single-value transfer routines..
  85.  * They automatically use the right size if we just have the right
  86.  * pointer type..
  87.  *
  88.  * This gets kind of ugly. We want to return _two_ values in "get_user()"
  89.  * and yet we don't want to do any pointers, because that is too much
  90.  * of a performance impact. Thus we have a few rather ugly macros here,
  91.  * and hide all the uglyness from the user.
  92.  */
  93. #define put_user(x,ptr) ({ \
  94. unsigned long __pu_addr = (unsigned long)(ptr); \
  95. __put_user_check((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
  96.  
  97. #define put_user_ret(x,ptr,retval) ({ \
  98. unsigned long __pu_addr = (unsigned long)(ptr); \
  99. __put_user_check_ret((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr)),retval); })
  100.  
  101. #define get_user(x,ptr) ({ \
  102. unsigned long __gu_addr = (unsigned long)(ptr); \
  103. __get_user_check((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
  104.  
  105. #define get_user_ret(x,ptr,retval) ({ \
  106. unsigned long __gu_addr = (unsigned long)(ptr); \
  107. __get_user_check_ret((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr)),retval); })
  108.  
  109. /*
  110.  * The "__xxx" versions do not do address space checking, useful when
  111.  * doing multiple accesses to the same area (the user has to do the
  112.  * checks by hand with "access_ok()")
  113.  */
  114. #define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
  115. #define __put_user_ret(x,ptr,retval) __put_user_nocheck_ret((x),(ptr),sizeof(*(ptr)),retval)
  116. #define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)),__typeof__(*(ptr)))
  117. #define __get_user_ret(x,ptr,retval) __get_user_nocheck_ret((x),(ptr),sizeof(*(ptr)),__typeof__(*(ptr)),retval)
  118.  
  119. struct __large_struct { unsigned long buf[100]; };
  120. #define __m(x) ((struct __large_struct *)(x))
  121.  
  122. #define __put_user_check(x,addr,size) ({ \
  123. register int __pu_ret; \
  124. if (__access_ok(addr,size)) { \
  125. switch (size) { \
  126. case 1: __put_user_asm(x,b,addr,__pu_ret); break; \
  127. case 2: __put_user_asm(x,h,addr,__pu_ret); break; \
  128. case 4: __put_user_asm(x,,addr,__pu_ret); break; \
  129. default: __pu_ret = __put_user_bad(); break; \
  130. } } else { __pu_ret = -EFAULT; } __pu_ret; })
  131.  
  132. #define __put_user_check_ret(x,addr,size,retval) ({ \
  133. register int __foo __asm__ ("l1"); \
  134. if (__access_ok(addr,size)) { \
  135. switch (size) { \
  136. case 1: __put_user_asm_ret(x,b,addr,retval,__foo); break; \
  137. case 2: __put_user_asm_ret(x,h,addr,retval,__foo); break; \
  138. case 4: __put_user_asm_ret(x,,addr,retval,__foo); break; \
  139. default: if (__put_user_bad()) return retval; break; \
  140. } } else return retval; })
  141.  
  142. #define __put_user_nocheck(x,addr,size) ({ \
  143. register int __pu_ret; \
  144. switch (size) { \
  145. case 1: __put_user_asm(x,b,addr,__pu_ret); break; \
  146. case 2: __put_user_asm(x,h,addr,__pu_ret); break; \
  147. case 4: __put_user_asm(x,,addr,__pu_ret); break; \
  148. default: __pu_ret = __put_user_bad(); break; \
  149. } __pu_ret; })
  150.  
  151. #define __put_user_nocheck_ret(x,addr,size,retval) ({ \
  152. register int __foo __asm__ ("l1"); \
  153. switch (size) { \
  154. case 1: __put_user_asm_ret(x,b,addr,retval,__foo); break; \
  155. case 2: __put_user_asm_ret(x,h,addr,retval,__foo); break; \
  156. case 4: __put_user_asm_ret(x,,addr,retval,__foo); break; \
  157. default: if (__put_user_bad()) return retval; break; \
  158. } })
  159.  
  160. #define __put_user_asm(x,size,addr,ret)                    \
  161. __asm__ __volatile__(                            \
  162.     "/* Put user asm, inline. */\n"                    \
  163. "1:\t"    "st"#size " %1, %2\n\t"                        \
  164.     "clr    %0\n"                            \
  165. "2:\n\n\t"                                \
  166.     ".section .fixup,#alloc,#execinstr\n\t"                \
  167.     ".align    4\n"                            \
  168. "3:\n\t"                                \
  169.     "b    2b\n\t"                            \
  170.     " mov    %3, %0\n\t"                        \
  171.         ".previous\n\n\t"                        \
  172.     ".section __ex_table,#alloc\n\t"                \
  173.     ".align    4\n\t"                            \
  174.     ".word    1b, 3b\n\t"                        \
  175.     ".previous\n\n\t"                        \
  176.        : "=&r" (ret) : "r" (x), "m" (*__m(addr)),            \
  177.      "i" (-EFAULT))
  178.  
  179. #define __put_user_asm_ret(x,size,addr,ret,foo)                \
  180. if (__builtin_constant_p(ret) && ret == -EFAULT)            \
  181. __asm__ __volatile__(                            \
  182.     "/* Put user asm ret, inline. */\n"                \
  183. "1:\t"    "st"#size " %1, %2\n\n\t"                    \
  184.     ".section __ex_table,#alloc\n\t"                \
  185.     ".align    4\n\t"                            \
  186.     ".word    1b, __ret_efault\n\n\t"                    \
  187.     ".previous\n\n\t"                        \
  188.        : "=r" (foo) : "r" (x), "m" (*__m(addr)));            \
  189. else                                    \
  190. __asm__ __volatile(                            \
  191.     "/* Put user asm ret, inline. */\n"                \
  192. "1:\t"    "st"#size " %1, %2\n\n\t"                    \
  193.     ".section .fixup,#alloc,#execinstr\n\t"                \
  194.     ".align    4\n"                            \
  195. "3:\n\t"                                \
  196.     "ret\n\t"                            \
  197.     " restore %%g0, %3, %%o0\n\t"                    \
  198.     ".previous\n\n\t"                        \
  199.     ".section __ex_table,#alloc\n\t"                \
  200.     ".align    4\n\t"                            \
  201.     ".word    1b, 3b\n\n\t"                        \
  202.     ".previous\n\n\t"                        \
  203.        : "=r" (foo) : "r" (x), "m" (*__m(addr)), "i" (ret))
  204.  
  205. extern int __put_user_bad(void);
  206.  
  207. #define __get_user_check(x,addr,size,type) ({ \
  208. register int __gu_ret; \
  209. register unsigned long __gu_val; \
  210. if (__access_ok(addr,size)) { \
  211. switch (size) { \
  212. case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; \
  213. case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \
  214. case 4: __get_user_asm(__gu_val,,addr,__gu_ret); break; \
  215. default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \
  216. } } else { __gu_val = 0; __gu_ret = -EFAULT; } x = (type) __gu_val; __gu_ret; })
  217.  
  218. #define __get_user_check_ret(x,addr,size,type,retval) ({ \
  219. register unsigned long __gu_val __asm__ ("l1"); \
  220. if (__access_ok(addr,size)) { \
  221. switch (size) { \
  222. case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; \
  223. case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \
  224. case 4: __get_user_asm_ret(__gu_val,,addr,retval); break; \
  225. default: if (__get_user_bad()) return retval; \
  226. } x = (type) __gu_val; } else return retval; })
  227.  
  228. #define __get_user_nocheck(x,addr,size,type) ({ \
  229. register int __gu_ret; \
  230. register unsigned long __gu_val; \
  231. switch (size) { \
  232. case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; \
  233. case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \
  234. case 4: __get_user_asm(__gu_val,,addr,__gu_ret); break; \
  235. default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \
  236. } x = (type) __gu_val; __gu_ret; })
  237.  
  238. #define __get_user_nocheck_ret(x,addr,size,type,retval) ({ \
  239. register unsigned long __gu_val __asm__ ("l1"); \
  240. switch (size) { \
  241. case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; \
  242. case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \
  243. case 4: __get_user_asm_ret(__gu_val,,addr,retval); break; \
  244. default: if (__get_user_bad()) return retval; \
  245. } x = (type) __gu_val; })
  246.  
  247. #define __get_user_asm(x,size,addr,ret)                    \
  248. __asm__ __volatile__(                            \
  249.     "/* Get user asm, inline. */\n"                    \
  250. "1:\t"    "ld"#size " %2, %1\n\t"                        \
  251.     "clr    %0\n"                            \
  252. "2:\n\n\t"                                \
  253.     ".section .fixup,#alloc,#execinstr\n\t"                \
  254.     ".align    4\n"                            \
  255. "3:\n\t"                                \
  256.     "clr    %1\n\t"                            \
  257.     "b    2b\n\t"                            \
  258.     " mov    %3, %0\n\n\t"                        \
  259.     ".previous\n\t"                            \
  260.     ".section __ex_table,#alloc\n\t"                \
  261.     ".align    4\n\t"                            \
  262.     ".word    1b, 3b\n\n\t"                        \
  263.     ".previous\n\t"                            \
  264.        : "=&r" (ret), "=&r" (x) : "m" (*__m(addr)),            \
  265.      "i" (-EFAULT))
  266.  
  267. #define __get_user_asm_ret(x,size,addr,retval)                \
  268. if (__builtin_constant_p(retval) && retval == -EFAULT)            \
  269. __asm__ __volatile__(                            \
  270.     "/* Get user asm ret, inline. */\n"                \
  271. "1:\t"    "ld"#size " %1, %0\n\n\t"                    \
  272.     ".section __ex_table,#alloc\n\t"                \
  273.     ".align    4\n\t"                            \
  274.     ".word    1b,__ret_efault\n\n\t"                    \
  275.     ".previous\n\t"                            \
  276.        : "=&r" (x) : "m" (*__m(addr)));                    \
  277. else                                    \
  278. __asm__ __volatile__(                            \
  279.     "/* Get user asm ret, inline. */\n"                \
  280. "1:\t"    "ld"#size " %1, %0\n\n\t"                    \
  281.     ".section .fixup,#alloc,#execinstr\n\t"                \
  282.     ".align    4\n"                            \
  283. "3:\n\t"                                \
  284.     "ret\n\t"                            \
  285.     " restore %%g0, %2, %%o0\n\n\t"                    \
  286.     ".previous\n\t"                            \
  287.     ".section __ex_table,#alloc\n\t"                \
  288.     ".align    4\n\t"                            \
  289.     ".word    1b, 3b\n\n\t"                        \
  290.     ".previous\n\t"                            \
  291.        : "=&r" (x) : "m" (*__m(addr)), "i" (retval))
  292.  
  293. extern int __get_user_bad(void);
  294.  
  295. extern __kernel_size_t __copy_user(void *to, void *from, __kernel_size_t size);
  296.  
  297. #define copy_to_user(to,from,n) ({ \
  298. void *__copy_to = (void *) (to); \
  299. __kernel_size_t __copy_size = (__kernel_size_t) (n); \
  300. __kernel_size_t __copy_res; \
  301. if(__copy_size && __access_ok((unsigned long)__copy_to, __copy_size)) { \
  302. __copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \
  303. } else __copy_res = __copy_size; \
  304. __copy_res; })
  305.  
  306. #define copy_to_user_ret(to,from,n,retval) ({ \
  307. if (copy_to_user(to,from,n)) \
  308.     return retval; \
  309. })
  310.  
  311. #define __copy_to_user(to,from,n)        \
  312.     __copy_user((void *)(to),        \
  313.             (void *)(from), n)
  314.  
  315. #define __copy_to_user_ret(to,from,n,retval) ({ \
  316. if (__copy_to_user(to,from,n)) \
  317.     return retval; \
  318. })
  319.  
  320. #define copy_from_user(to,from,n) ({ \
  321. void *__copy_to = (void *) (to); \
  322. void *__copy_from = (void *) (from); \
  323. __kernel_size_t __copy_size = (__kernel_size_t) (n); \
  324. __kernel_size_t __copy_res; \
  325. if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \
  326. __copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \
  327. } else __copy_res = __copy_size; \
  328. __copy_res; })
  329.  
  330. #define copy_from_user_ret(to,from,n,retval) ({ \
  331. if (copy_from_user(to,from,n)) \
  332.     return retval; \
  333. })
  334.  
  335. #define __copy_from_user(to,from,n)        \
  336.     __copy_user((void *)(to),        \
  337.             (void *)(from), n)
  338.  
  339. #define __copy_from_user_ret(to,from,n,retval) ({ \
  340. if (__copy_from_user(to,from,n)) \
  341.     return retval; \
  342. })
  343.  
  344. extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size)
  345. {
  346.   __kernel_size_t ret;
  347.   __asm__ __volatile__ ("
  348.     .section __ex_table,#alloc
  349.     .align 4
  350.     .word 1f,3
  351.     .previous
  352. 1:
  353.     mov %2, %%o1
  354.     call __bzero
  355.      mov %1, %%o0
  356.     mov %%o0, %0 
  357.     " : "=r" (ret) : "r" (addr), "r" (size) :
  358.     "o0", "o1", "o2", "o3", "o4", "o5", "o7",
  359.     "g1", "g2", "g3", "g4", "g5", "g7", "cc");
  360.   return ret;
  361. }
  362.  
  363. #define clear_user(addr,n) ({ \
  364. void *__clear_addr = (void *) (addr); \
  365. __kernel_size_t __clear_size = (__kernel_size_t) (n); \
  366. __kernel_size_t __clear_res; \
  367. if(__clear_size && __access_ok((unsigned long)__clear_addr, __clear_size)) { \
  368. __clear_res = __clear_user(__clear_addr, __clear_size); \
  369. } else __clear_res = __clear_size; \
  370. __clear_res; })
  371.  
  372. #define clear_user_ret(addr,size,retval) ({ \
  373. if (clear_user(addr,size)) \
  374.     return retval; \
  375. })
  376.  
  377. extern int __strncpy_from_user(unsigned long dest, unsigned long src, int count);
  378.  
  379. #define strncpy_from_user(dest,src,count) ({ \
  380. unsigned long __sfu_src = (unsigned long) (src); \
  381. int __sfu_count = (int) (count); \
  382. long __sfu_res = -EFAULT; \
  383. if(__access_ok(__sfu_src, __sfu_count)) { \
  384. __sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \
  385. } __sfu_res; })
  386.  
  387. extern int __strlen_user(const char *);
  388.  
  389. extern __inline__ int strlen_user(const char *str)
  390. {
  391.     if(!access_ok(VERIFY_READ, str, 0))
  392.         return 0;
  393.     else
  394.         return __strlen_user(str);
  395. }
  396.  
  397. #endif  /* __ASSEMBLY__ */
  398.  
  399. #endif /* _ASM_UACCESS_H */
  400.